#include "PortMappingThread.h"

PortMappingThread::PortMappingThread(QObject *parent) :
    QThread(parent) {
    currentOperation = NONE;
}

void PortMappingThread::setLocalIP(QString localIP) {
    localIPString = localIP;
}

void PortMappingThread::checkPort() {
    currentOperation = CHECKING;
    start();
}

void PortMappingThread::forwardPort() {
    currentOperation = FORWARDING;
    start();
}

void PortMappingThread::deletePort() {
    currentOperation = DELETING;
    start();
}

void PortMappingThread::run() {
    if (currentOperation == FORWARDING) {
        emit portStatusChanged(Network::SEARCHING);
    }
    int error;
    struct UPNPDev * devlist = upnpDiscover(2000, NULL, NULL, 0, 0, &error);
    if (error) {
        emit portStatusChanged(Network::ERROR);
        return;
    }

    if (currentOperation == FORWARDING) {
        emit portStatusChanged(Network::VALIDATING);
    }
    struct UPNPUrls urls;
    struct IGDdatas data;
    char lanaddr[64];
    int result;
    result = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
    if (result != 1) {
        emit portStatusChanged(Network::ERROR);
        return;
    }

    if (currentOperation == FORWARDING) {
        emit portStatusChanged(Network::FORWARDING);
        result = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, PORT_STRING, PORT_STRING, localIPString.toUtf8().constData(), NULL, "TCP", NULL, "0");
        if (result == UPNPCOMMAND_SUCCESS) {
            emit portStatusChanged(Network::FORWARDED);
            return;
        } else {
            emit portStatusChanged(Network::ERROR);
            return;
        }
    } else if (currentOperation == DELETING) {
        result = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, PORT_STRING, "TCP", NULL);
        if (result == UPNPCOMMAND_SUCCESS) {
            emit portStatusChanged(Network::NOT_FORWARDED);
            return;
        } else {
            emit portStatusChanged(Network::ERROR);
            return;
        }
    } else if (currentOperation == CHECKING) {
        int i = 1;
        char index[6], intClient[40], intPort[6], extPort[6];
        char protocol[4], desc[80], enabled[6], rHost[64], duration[16];
        QString currentIPString;
        do {
            qsnprintf(index, 6, "%d", i);
            rHost[0] = '\0'; enabled[0] = '\0';
            duration[0] = '\0'; desc[0] = '\0';
            extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0';
            result = UPNP_GetGenericPortMappingEntry(urls.controlURL, data.first.servicetype, index, extPort, intClient, intPort, protocol, desc, enabled, rHost, duration);
            currentIPString = QString(intClient);
            if (result == 0) {
                if (intPort[0] == '2' && intPort[1] == '2') {
                    if (currentIPString.compare(localIPString)) {
                        if (protocol[0] == 'T' && protocol[1] == 'C' && protocol[2] == 'P') {

                            break;
                        }
                    }
                }
            }
            i++;
        } while (result == 0);
    }
}
